import { IWebSocketProxy } from "tsrpc-base-client";
import { TsrpcError } from "tsrpc-proto";
import WebSocket from 'ws';

/**
 * @internal
 */
export class WebSocketProxy implements IWebSocketProxy {

    options!: IWebSocketProxy['options']

    private _ws?: WebSocket;
    connect(server: string, protocols?: string[]): void {
        this._ws = new WebSocket(server, protocols);
        this._ws.onopen = this.options.onOpen;
        this._ws.onclose = e => {
            this.options.onClose(e.code, e.reason);
            this._ws = undefined;
        }
        this._ws.onerror = e => {
            this.options.onError(e.error);
        }
        this._ws.onmessage = e => {
            if (e.data instanceof ArrayBuffer) {
                this.options.onMessage(new Uint8Array(e.data));
            }
            else if (Array.isArray(e.data)) {
                this.options.onMessage(Buffer.concat(e.data));
            }
            else {
                this.options.onMessage(e.data);
            }
        }
    }
    close(code?: number, reason?: string): void {
        this._ws?.close(code, reason);
        this._ws = undefined;
    }
    send(data: string | Uint8Array): Promise<{ err?: TsrpcError | undefined; }> {
        return new Promise(rs => {
            this._ws?.send(data, err => {
                if (err) {
                    this.options.logger?.error('WebSocket Send Error:', err);
                    rs({
                        err: new TsrpcError('Network Error', {
                            code: 'SEND_BUF_ERR',
                            type: TsrpcError.Type.NetworkError,
                            innerErr: err
                        })
                    });
                    return;
                }
                rs({});
            });
        })
    }

}